home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OWLSRC.PAK / RCNTFILE.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  10KB  |  372 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.14  $
  6. //
  7. // Implementation of class TRecentFiles
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #if !defined(OWL_FRAMEWIN_H)
  11. # include <owl/framewin.h>
  12. #endif
  13. #if !defined(WINSYS_PROFILE_H)
  14. # include <winsys/profile.h>
  15. #endif
  16. #if !defined(OWL_RCNTFILE_H)
  17. # include <owl/rcntfile.h>
  18. #endif
  19. #if !defined(CLASSLIB_POINTER_H)
  20. # include <classlib/pointer.h>
  21. #endif
  22. #if !defined(OWL_WINDOW_RH)
  23. # include <owl/window.rh>
  24. #endif
  25. #if !defined(OWL_EDITFILE_RH)
  26. # include <owl/editfile.rh>
  27. #endif
  28. #include <stdio.h>
  29.  
  30. OWL_DIAGINFO;
  31.  
  32. #if defined(BI_NAMESPACE)
  33. namespace OWL {
  34. #endif
  35.  
  36. const int CM_MRU_FIRST      = 31990;
  37. const int CM_MRU_LAST       = CM_MRU_FIRST + TRecentFiles::MaxMenuItems;
  38.  
  39. const char* Section   = "MRU";
  40. const char* CountKey  = "Count";
  41. const char* MruPrefix = "MRU";
  42. const char* MenuItemDefault = "Default";
  43. const int   MaxMenuItemLen = 255;
  44. uint TRecentFiles::MruMessage = 0;
  45.  
  46. #if defined(BI_NAMESPACE)
  47. } // namespace OWL
  48. #endif
  49.  
  50. IMPLEMENT_CASTABLE(TRecentFiles);
  51.  
  52. //
  53. // Response Table to catch the items selected from the menu.
  54. //
  55. DEFINE_RESPONSE_TABLE1(TRecentFiles, TEventHandler)
  56.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 0, CmFile),
  57.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 1, CmFile),
  58.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 2, CmFile),
  59.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 3, CmFile),
  60.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 4, CmFile),
  61.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 5, CmFile),
  62.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 6, CmFile),
  63.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 7, CmFile),
  64.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 8, CmFile),
  65.   EV_COMMAND_AND_ID(CM_MRU_FIRST + 9, CmFile),
  66.   EV_COMMAND_ENABLE(CM_EXIT, CeExit),
  67. END_RESPONSE_TABLE;
  68.  
  69. //
  70. // Constructor to initialize the external storage and the maximum number of
  71. // items to save in the most-recently-used (MRU) list.
  72. //
  73. TRecentFiles::TRecentFiles(const char far* iniName, int numSavedFiles)
  74. :
  75.   AddedSeparator(false),
  76.   LastHMenu(0)
  77. {
  78.   MaxFilesToSave = min(numSavedFiles, (int)MaxMenuItems);
  79.   Profile        = new TProfile(Section, iniName);
  80.   SetMaxMruItems(MaxFilesToSave);
  81.   MruMessage     = ::RegisterWindowMessage(MruFileMessage);
  82. }
  83.  
  84. //
  85. // Deletes the allocated profile.
  86. //
  87. TRecentFiles::~TRecentFiles()
  88. {
  89.   delete Profile;
  90. }
  91.  
  92. //
  93. // Sets the maximum number of items that can be saved with this MRU.
  94. //
  95. void
  96. TRecentFiles::SetMaxMruItems(int max)
  97. {
  98.   Profile->WriteInt(CountKey, max);
  99.   Profile->Flush();
  100. }
  101.  
  102. //
  103. // Respond to a menu item selection
  104. //
  105. void
  106. TRecentFiles::CmFile(uint id)
  107. {
  108.   TApplication* app    = TYPESAFE_DOWNCAST(this, TApplication);
  109.   TFrameWindow* window = app ? app->GetMainWindow() : 0;
  110.  
  111.   if (window) {
  112.     // Foward menu selection command to specified target
  113.     //
  114.     window->SendMessage(MruMessage, id, 0);
  115.   }
  116. }
  117.  
  118. //
  119. // Searches the menu to find the position of a menu item.
  120. //
  121. int
  122. TRecentFiles::GetMenuPos(HMENU menu, uint id)
  123. {
  124.   for (int i = ::GetMenuItemCount(menu) - 1; i >= 0; i--)
  125.     if (::GetMenuItemID(menu, i) == id)
  126.       return i;
  127.   return -1;
  128. }
  129.  
  130. //
  131. // Retrieve the menu position of the CM_EXIT menu item.
  132. // Returns -1 if not found.
  133. //
  134. int
  135. TRecentFiles::GetExitMenuPos(HMENU hMenu)
  136. {
  137.   int exitPos = GetMenuPos(hMenu, CM_EXIT);
  138.   return exitPos;
  139. }
  140.  
  141. //
  142. // Returns true if the menu has any MRU items in it.
  143. //
  144. bool
  145. TRecentFiles::MruItemsInsertedIntoMenu(HMENU hMenu)
  146. {
  147.   int menuPos = GetMenuPos(hMenu, CM_MRU_FIRST + 0);
  148.   return menuPos != -1;
  149. }
  150.  
  151. //
  152. // Removes the MRU items from the menu.
  153. //
  154. void
  155. TRecentFiles::RemoveMruItemsFromMenu(HMENU hMenu)
  156. {
  157.   int exitPos = GetExitMenuPos(hMenu);
  158.   if (exitPos > 1)
  159.     if (::GetMenuItemID(hMenu, exitPos - 1) == 0 && AddedSeparator) {
  160.       AddedSeparator = false;
  161.       if (LastHMenu == hMenu)
  162.         ::RemoveMenu(hMenu, exitPos - 1, MF_BYPOSITION);
  163.     }
  164.  
  165.   // remove MRU items
  166.   //
  167.   if (MruItemsInsertedIntoMenu(hMenu)) {
  168.     for (int i = CM_MRU_FIRST; i < CM_MRU_LAST; i++) {
  169.       int menuPos = GetMenuPos(hMenu, i);
  170.       if (menuPos != -1) {
  171.         ::RemoveMenu(hMenu, i, MF_BYCOMMAND);
  172.       }
  173.     }
  174.   }
  175. }
  176.  
  177. //
  178. // Reads external information and adds the MRU items into the menu.
  179. // Adds a separator between the MRU items and the exit menu item.
  180. //
  181. void
  182. TRecentFiles::InsertMruItemsToMenu(HMENU hMenu)
  183. {
  184.   TAPointer<char> keyBuffer      = new char[80];
  185.   TAPointer<char> tempBuffer     = new char[MaxMenuItemLen];
  186.   TAPointer<char> menuItemBuffer = new char[MaxMenuItemLen];
  187.  
  188.   TMenu menu(hMenu);
  189.   int exitPos       = GetExitMenuPos(hMenu);
  190.   int count         = GetMruCount();
  191.   int i;
  192.   int numItemsAdded = 0;
  193.  
  194.   for (i = 0; i < count; i++) {
  195.     sprintf(keyBuffer, "%s%d", MruPrefix, i);
  196.     tempBuffer[0] = 0;
  197.     Profile->GetString(keyBuffer, tempBuffer, MaxMenuItemLen, MenuItemDefault);
  198.  
  199.     if (tempBuffer[0] == 0)
  200.       continue;
  201.     if (strcmp(tempBuffer, MenuItemDefault) == 0)    // key not found
  202.       continue;
  203.  
  204.     numItemsAdded++;
  205.     sprintf(menuItemBuffer, "&%d %s", i + 1, (char*)tempBuffer);
  206.     menu.InsertMenu(exitPos + i, MF_BYPOSITION | MF_STRING, CM_MRU_FIRST + i, menuItemBuffer);
  207.   }
  208.  
  209.   if (numItemsAdded > 0) {
  210.     if (AddedSeparator == false) {
  211.       LastHMenu = hMenu;
  212.       AddedSeparator = true;
  213.       tempBuffer[0] = 0;
  214.       ::InsertMenu(hMenu, exitPos + numItemsAdded, MF_BYPOSITION | MF_SEPARATOR, 0, tempBuffer);
  215.     }
  216.   }
  217. }
  218.  
  219. //
  220. // Reads information in the external storage to display the menu choices.
  221. //
  222. void
  223. TRecentFiles::CeExit(TCommandEnabler& ce)
  224. {
  225.   ce.Enable(true);
  226.  
  227.   TMenuItemEnabler* me = TYPESAFE_DOWNCAST(&ce, TMenuItemEnabler);
  228.   if (me == 0)
  229.     return;
  230.  
  231.   HMENU hMenu = me->GetMenu();
  232.   RemoveMruItemsFromMenu(hMenu);
  233.   InsertMruItemsToMenu(hMenu);
  234. }
  235.  
  236. //
  237. // Retrieves the text of the choice based on the id.
  238. //
  239. bool
  240. TRecentFiles::GetMenuText(int id, char far* text, int maxTextLen)
  241. {
  242.   id -= CM_MRU_FIRST;
  243.   int count = GetMruCount();
  244.   if (id < 0 || count <= id)
  245.     return false;
  246.   TAPointer<char> keyBuffer = new char[80];
  247.   sprintf(keyBuffer, "%s%d", MruPrefix, id);
  248.   bool successful = Profile->GetString(keyBuffer, text, maxTextLen);
  249.   return successful;
  250. }
  251.  
  252. //
  253. // Saves the menu choice into the profile.
  254. //
  255. void
  256. TRecentFiles::SaveMenuChoice(const char far* text)
  257. {
  258.   int index = GetMruItemIndex(text);
  259.   RemoveMruIndex(index);
  260.   AddMruItem(text);
  261. }
  262.  
  263. //
  264. // Return the number of files that are currently in the MRU list.
  265. //
  266. int
  267. TRecentFiles::GetMruCount()
  268. {
  269.   return Profile->GetInt(CountKey, MaxFilesToSave);
  270. }
  271.  
  272. //
  273. // Removes the MRU item at index.
  274. // Shuffles the items below index up.
  275. //
  276. void
  277. TRecentFiles::RemoveMruIndex(int index)
  278. {
  279.   int count = GetMruCount();
  280.   if (index < 0 || count <= index)
  281.     return;
  282.  
  283.   TAPointer<char> srcKeyBuffer = new char[80];
  284.   TAPointer<char> dstKeyBuffer = new char[80];
  285.   TAPointer<char> menuText     = new char[MaxMenuItemLen];
  286.  
  287.   if (index != count - 1) {
  288.     // shuffle so the item to be deleted is at index count-1
  289.     //
  290.     for (int i = index; i < count - 1; i++) {
  291.       sprintf(srcKeyBuffer, "%s%d", MruPrefix, i + 1);
  292.       Profile->GetString(srcKeyBuffer, menuText, MaxMenuItemLen, MenuItemDefault);
  293.       sprintf(dstKeyBuffer, "%s%d", MruPrefix, i);
  294.       if (strcmp(menuText, MenuItemDefault) == 0)
  295.         menuText[0] = 0;
  296.       Profile->WriteString(dstKeyBuffer, menuText);
  297.     }
  298.   }
  299.  
  300.   // delete the last item
  301.   //
  302.   sprintf(dstKeyBuffer, "%s%d", MruPrefix, count - 1);
  303.   menuText[0] = 0;
  304.   Profile->WriteString(dstKeyBuffer, menuText);
  305.   Profile->Flush();
  306. }
  307.  
  308. //
  309. // Adds an item into the top of the MRU list.
  310. // If there is a duplicate, the item is moved from its current position
  311. // to the top of the list.
  312. //
  313. void
  314. TRecentFiles::AddMruItem(const char far* text)
  315. {
  316.   TAPointer<char> srcKeyBuffer = new char[80];
  317.   TAPointer<char> dstKeyBuffer = new char[80];
  318.   TAPointer<char> menuText     = new char[MaxMenuItemLen];
  319.  
  320.   int count = GetMruCount();
  321.  
  322.   if (count > 0) {
  323.     // Shuffle items down to make room at index 0
  324.     //
  325.     for (int i = count - 1; i >= 0; i--) {
  326.       sprintf(srcKeyBuffer, "%s%d", MruPrefix, i);
  327.       Profile->GetString(srcKeyBuffer, menuText, MaxMenuItemLen, MenuItemDefault);
  328.       sprintf(dstKeyBuffer, "%s%d", MruPrefix, i + 1);
  329.       if (strcmp(menuText, MenuItemDefault) == 0) {
  330.         menuText[0] = 0;
  331.         continue;
  332.       }
  333.       Profile->WriteString(dstKeyBuffer, menuText);
  334.     }
  335.   }
  336.  
  337.   // Add item to the top of the list
  338.   //
  339.   sprintf(dstKeyBuffer, "%s%d", MruPrefix, 0);
  340.   Profile->WriteString(dstKeyBuffer, text);
  341.   Profile->Flush();
  342. }
  343.  
  344. //
  345. // Returns true if there are any items in the MRU list matches the text.
  346. //
  347. bool
  348. TRecentFiles::ExistMruItem(const char far* text)
  349. {
  350.   return GetMruItemIndex(text) != -1;
  351. }
  352.  
  353. //
  354. // Returns the index of the MRU item containing text.
  355. // Returns -1 if not found.
  356. //
  357. int
  358. TRecentFiles::GetMruItemIndex(const char far* text)
  359. {
  360.   TAPointer<char> srcKeyBuffer = new char[80];
  361.   TAPointer<char> menuText     = new char[MaxMenuItemLen];
  362.  
  363.   int count = GetMruCount();
  364.   for (int i = 0; i < count; i++) {
  365.     sprintf(srcKeyBuffer, "%s%d", MruPrefix, i);
  366.     Profile->GetString(srcKeyBuffer, menuText, MaxMenuItemLen, MenuItemDefault);
  367.     if (strcmpi(text, menuText) == 0)
  368.       return i;
  369.   }
  370.   return -1;
  371. }
  372.